feat(web): acknowledged shared tx publishing - #3727
Conversation
Codecov Report❌ Patch coverage is @@ Coverage Diff @@
## main #3727 +/- ##
==========================================
+ Coverage 77.83% 77.89% +0.05%
==========================================
Files 1329 1333 +4
Lines 126868 127430 +562
Branches 11035 11092 +57
==========================================
+ Hits 98746 99257 +511
- Misses 24968 25015 +47
- Partials 3154 3158 +4
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 3 files with indirect coverage changes 🚀 New features to boost your workflow:
|
Greptile SummaryThis change adds acknowledged browser publishing to shared robot transmit channels, with relay correlation and SDK receipt handling. Two command-delivery reliability problems were reproduced: Confidence Score: 3/5Not safe to merge until disconnect-state handling and post-delivery acknowledgement semantics are corrected. Focused executable checks reproduced both independent command-delivery failures with captured source and runtime output. The SDK check exercised the real session and transport lifecycle; the bridge check exercised the checked-out frame handler with both healthy and raising subscriber paths. Files Needing Attention:
What T-Rex did
|
89e4f57 to
b78600a
Compare
b78600a to
8bd5bdf
Compare
8bd5bdf to
34fbf18
Compare
34fbf18 to
225ddce
Compare
225ddce to
69a3bb9
Compare
- Protocol v5 grows pub/pub_ack/pub_nack and error.requestId (no version bump: unknown messages drop, nothing misparses). New golden vectors pin the messages and the forwarded tx-frame shape on both sides. - ChannelSpec gains additive publish/requiredScope manifest fields with mirrored domain rules (invalid_publish, invalid_scope). Normalized manifests now always emit both, so the golden manifests changed (normalization idempotence forces it). - Channel(dir="tx", publish="shared") compiles: generated Out port, decoder resolved via the new resolve_decoder (registered @web_decoder or generic json.v1 for scalars/dicts/lists; dataclasses need an explicit decoder). text.json.v1 joins the built-ins. publish="exclusive" stays gated (W8). - The relay validates pub in spec order (watch, dup id, 32 KiB cap, policy, scope bypass for the synthetic local principal, per-viewer + aggregate token buckets at maxHz, pending count/byte caps), stamps provenance, and forwards the JSON as a tx data frame on the robot carrier. The forwarded id is a relay-authored token, translated back to the viewer's own id on ack, so viewer-chosen ids stay untrusted and cannot collide. - Pending settles exactly once: bridge ack/nack routed to the one live sender, publish_timeout via the reap sweep, robot_disconnected on robot death, silent release on viewer death. Counts land in /api/stats. - The bridge dispatches carrier tx frames from the ordered control queue, decodes with the resolved codec (PublishContext when the signature takes it), verifies the declared message type, calls Out.publish(), and only then acks on a robot-opened one-shot @control stream. Failures nack with bounded messages and never recycle the session. - SDK session.publish() -> Promise<PublishReceipt>: stable local rejection codes, bounded pending map, outcome "rejected" for definite failures vs "unknown" for connection loss/timeouts, and no automatic resend ever. Correlated errors bypass the hello handshake slot (they could previously unblock a hello() retry) and never touch the session error banner. - examples/chat-input/ is the end-to-end publish demo, pinned by a new chromium e2e in CI (test_publish_browser.py) plus a Python-viewer e2e.
The block calls cockpit() without imports, so md-babel failed on it in CI.
817db54 to
00bb47a
Compare
Isn't this a safety risk? There should always be one clear owner of hardware such that the robot should not have conflicting instructions. |
This is already the case. The relay enforces one client controlling the robot at a time (it has to arm by sending teleop_start and wait to receive teleop_started). This PR lets you declare other channels onto which different clients can send. This is not intended for teleoping, but for other reasons where two clients would need to send messages simultaneously. This is the case for the chat for example. If you have two clients viewing the same robot, they should both be able to interact with chat. You shouldn't have to "arm" chat to type something in chat. Note that "shared" is not the default. You have to opt into it and someone should be careful to not use it to send cmd_vel commands. |
session.publish()to the web SDK. Each call receives confirmation once the bridge has published the message onto the stream.